import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Random;

public class Main {

    public static void main(String[] args) {

        JFrame frame = new JFrame();
        MyJPanel jPanel = new MyJPanel();
        frame.add(jPanel);
        ArrayList<Ball> balls = new ArrayList<Ball>();
        Random random = new Random();
        for (int i = 0;i<800;i++){
            Ball ball = new Ball(800*Math.random(), 100*Math.random(), 5, 400*Math.random()-200, 100*Math.random()-50);
            ball.setElastic(80);
            ball.setAy(98);
            ball.setColor(new Color(random.nextInt(255*255*255)));
           balls.add(ball);
        }

        jPanel.setBall(balls);
        int a = 10;
        frame.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
                if(e.getKeyCode() == 37) {
                    Ball ball = balls.get(0);
                    ball.setVx(ball.getVx() - a);
                }else if(e.getKeyCode() == 38) {
                    Ball ball = balls.get(0);
                    ball.setVy(ball.getVy() - a);
                }else if(e.getKeyCode() == 39) {
                    Ball ball = balls.get(0);
                    ball.setVx(ball.getVx() + a);
                }else if(e.getKeyCode() == 40) {
                    Ball ball = balls.get(0);
                    ball.setVy(ball.getVy() + a);
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {
                super.keyReleased(e);
                if(e.getKeyCode() == 37) {
                    Ball ball = balls.get(0);
                    ball.setVx(ball.getVx() + a);
                }else if(e.getKeyCode() == 38) {
                    Ball ball = balls.get(0);
                    ball.setVy(ball.getVy() + a);
                }else if(e.getKeyCode() == 39) {
                    Ball ball = balls.get(0);
                    ball.setVx(ball.getVx() - a);
                }else if(e.getKeyCode() == 40) {
                    Ball ball = balls.get(0);
                    ball.setVy(ball.getVy() + a);
                }
            }
        });
        //设置窗口是否可见
        frame.setVisible(true);
        //设置窗口大小
        frame.setSize(800,800);
        //设置窗口位置
        frame.setLocationRelativeTo(null);
        //设置窗口标题
        frame.setTitle("球球");
//        frame.getContentPane().setBackground(Color.DARK_GRAY);
//        jPanel.setBackground(Color.blue);
        //重复绘制
        while (true){
            createObj(balls, 25);
            frame.repaint();
            try {
                Thread.sleep(15);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
    // 右边墙
    static double rightWall = 750;
    // 左边墙
    static double leftWall = 50;
    // 运动
    static void createObj(ArrayList<Ball> balls, int millis) {
        float t = (float) (millis/1000.0);
        for (Ball ball:balls) {
            double x = ball.getX();
            double y = ball.getY();
            double r = ball.getR();
            double vx = ball.getVx();
            double vy = ball.getVy();
            double ax = ball.getAx();
            double ay = ball.getAy();
            ball.setX(x + vx * t);
            ball.setY(y + vy * t);
            ball.setVy(vy + ay * t);
            ball.setVx(vx + ax * t);

            // 撞地板
            if(y > 700) {
                ball.setVy((0 - ball.getVy())/Math.sqrt(2));
                ball.setVy(ball.getVy() * ball.getElastic() / 100.0);
                ball.setY(700);
            }
            // 撞侧墙
            if ((x>rightWall)){
                ball.setVx(-ball.getVx());
                ball.setVx(ball.getVx() * ball.getElastic() / 100.0);
                ball.setX(rightWall);
            }
            if ((x<leftWall)){
                ball.setVx(-ball.getVx());
                ball.setVx(ball.getVx() * ball.getElastic() / 100.0);
                ball.setX(leftWall);
            }

        }
        // 碰撞
        for(int i = 0; i < balls.size() - 1; i++) {
            for(int j = i+1; j < balls.size(); j++) {
                crash(balls.get(i), balls.get(j));
            }
        }
    }

    // 检测两球碰撞
    private static void crash(Ball ball1, Ball ball2) {
        double deltax = ball1.getX()-ball2.getX();
        double deltay = ball1.getY()-ball2.getY();
        double distance = Math.sqrt(deltax*deltax+deltay*deltay);
        //记球心连线与x轴夹角为theta
        double theta = Math.atan(deltay/deltax);

        if (distance <= ball1.getR() + ball2.getR()){
            changeV2(ball1, ball2, theta);
            // 调整相切
            double move = (distance - ball1.getR() - ball2.getR()) / 2;
            double moveX = Math.abs(move * Math.cos(theta));
            double moveY = Math.abs(move * Math.sin(theta));
            ball1.setX(ball1.getX() + (ball1.getX() - ball2.getX() > 0 ? moveX : -moveX));
            ball1.setY(ball1.getY() + (ball1.getY() - ball2.getY() > 0 ? moveY : -moveY));
            ball2.setX(ball2.getX() + (ball2.getX() - ball1.getX() > 0 ? moveX : -moveX));
            ball2.setY(ball2.getY() + (ball2.getY() - ball1.getY() > 0 ? moveY : -moveY));
        }
    }

    // 交换速度
    private static void changeV2(Ball ball1, Ball ball2, double theta) {
        double cos = Math.cos(theta);
        double sin = Math.sin(theta);
        double v1TotalX = ball1.getVx();
        double v1TotalY = ball1.getVy();
        double v2TotalX = ball2.getVx();
        double v2TotalY = ball2.getVy();

        double deltax = ball1.getX()-ball2.getX();
        double deltay = ball1.getY()-ball2.getY();
        double distance = Math.sqrt(deltax*deltax+deltay*deltay);
        double move = ball1.getR() + ball2.getR() - distance;

        // v连
        double v1Circle = (v1TotalX * cos + v1TotalY * sin) * ball1.getElastic() / 100.0;
        double v1CircleX = v1Circle * cos;
        double v1CircleY = v1Circle * sin;
        // v垂
        double v1LeftX = v1TotalX - v1CircleX;
        double v1LeftY = v1TotalY - v1CircleY;

        // v连
        double v2Circle = (v2TotalX * cos + v2TotalY * sin) * ball2.getElastic() / 100.0;
        double v2CircleX = v2Circle * cos;
        double v2CircleY = v2Circle * sin;
        // v垂
        double v2LeftX = v2TotalX - v2CircleX;
        double v2LeftY = v2TotalY - v2CircleY;

        ball1.setVx(v1LeftX + v2CircleX);
        ball1.setVy(v1LeftY + v2CircleY);
        ball2.setVx(v2LeftX + v1CircleX);
        ball2.setVy(v2LeftY + v1CircleY);
    }



}
